package ar.com.algotres.tpdos.model.juego;

import java.util.ArrayList;
import java.util.List;

import ar.com.algotres.tpdos.model.aviones.Avion;
import ar.com.algotres.tpdos.model.aviones.EstadoAvion;
import ar.com.algotres.tpdos.model.aviones.FabricaAviones;
import ar.com.algotres.tpdos.model.controlador.ITorreDeControl;
import ar.com.algotres.tpdos.model.controlador.TorreDeControl;
import ar.com.algotres.tpdos.model.mapas.Mapa;
import ar.com.algotres.tpdos.views.juego.IVistaJuego;
import ar.com.algotres.tpdos.views.observadores.ObservadorDeAterrizajes;
import ar.com.algotres.tpdos.views.observadores.ObservadorDeAvionesVolando;
import ar.uba.fi.algo3.titiritero.ObjetoVivo;

public class Juego implements ObjetoVivo {
	
	private Integer cantidadAvionesAterrizados = 0;
	private Integer cantidadAvionesVolando = 0;
	private IVistaJuego vistaJuego;
	private ObservadorDeAterrizajes observadorAterrizajes;
	private ObservadorDeAvionesVolando observadorAvionesVolando;
	private ITorreDeControl torreDeControl;
	private Nivel nivel;

	public Juego(IVistaJuego vistaJuego,
			ObservadorDeAterrizajes observadorAterrizajes, 
			ObservadorDeAvionesVolando observadorDeAvionesVolando) {
		this.vistaJuego = vistaJuego;
		this.observadorAterrizajes = observadorAterrizajes;
		this.observadorAvionesVolando = observadorDeAvionesVolando;

	}

	public void comenzar(Nivel nivel) {
		this.nivel = nivel;
		this.cantidadAvionesAterrizados = 0;
		this.cantidadAvionesVolando = 0;
		torreDeControl = crearTorreDeControl(this.nivel.getMapa());
		vistaJuego.torreDeControlCreada(torreDeControl);
		vistaJuego.mapaCreado(this.nivel.getMapa());

	}

	//Es protected para poder testearlo
	protected ITorreDeControl crearTorreDeControl(Mapa mapa) {
		return new TorreDeControl(mapa);
	}

	public void recuperar(Juego juegoRecuperado) {

		vistaJuego.juegoTerminado();
		this.cantidadAvionesAterrizados = juegoRecuperado
				.getCantidadAvionesAterrizados();
		
		this.nivel = juegoRecuperado.getNivel();
		this.torreDeControl = juegoRecuperado.getTorreDeControl();
		int cantidadAvionesVolandoJuegoRecuperado = 0;
		for (Avion avion : torreDeControl.getAviones()){
			if (!EstadoAvion.ATERRIZADO.equals(avion.getEstado())){
				cantidadAvionesVolandoJuegoRecuperado++;
			}
		}
		this.cantidadAvionesVolando = cantidadAvionesVolandoJuegoRecuperado;
		vistaJuego.torreDeControlCreada(torreDeControl);
		this.vistaJuego.mapaCreado(nivel.getMapa());

		for (Avion avion : torreDeControl.getAviones()) {
			avion.avionCreado(vistaJuego);
		}

	}

	public void vivir() {

		List<Avion> avionesAterrizados = new ArrayList<Avion>();

		for (Avion avion : torreDeControl.getAviones()) {
			avion.mover();
			if (avion.getEstado().equals(EstadoAvion.ATERRIZADO)) {
				cantidadAvionesAterrizados++;
				cantidadAvionesVolando--;
				avionesAterrizados.add(avion);
				vistaJuego.avionAterrizado(avion);
			}
		}

		torreDeControl.getAviones().removeAll(avionesAterrizados);

		if (torreDeControl.cantidadAvionesVolando() <= nivel.getFactorAparicion()) {
			crearAvionSimple();
			crearAvionHelicoptero();
			crearAvionPesado();
			crearAvionComputarizado();
			cantidadAvionesVolando+=4;
		}

		observadorAterrizajes.seActualizaronLosAterrizajes(
				cantidadAvionesAterrizados,
				nivel.getCantidadAvionesAAterrizar());
		observadorAvionesVolando.seActualizaronLosAvionesVolando(cantidadAvionesVolando);
		if (cantidadAvionesAterrizados >= nivel.getCantidadAvionesAAterrizar()) {
			cantidadAvionesAterrizados = 0;
			torreDeControl.getAviones().clear();
			vistaJuego.juegoGanado();
			vistaJuego.juegoTerminado();

		}

		if (torreDeControl.huboColisiones()) {
			cantidadAvionesAterrizados = 0;
			torreDeControl.getAviones().clear();
			vistaJuego.juegoPerdido();
			vistaJuego.juegoTerminado();
		}
	}

	private Avion crearAvionComputarizado() {
		Avion avionComputarizado = FabricaAviones
				.makeAvionComputarizado(torreDeControl, nivel.getVelocidad());
		torreDeControl.agregarAvion(avionComputarizado);
		vistaJuego.avionComputarizadoCreado(avionComputarizado);
		return avionComputarizado;
	}

	private Avion crearAvionSimple() {
		Avion avionSimple = FabricaAviones.makeAvionSimple(torreDeControl, nivel.getVelocidad());
		torreDeControl.agregarAvion(avionSimple);
		vistaJuego.avionSimpleCreado(avionSimple);
		return avionSimple;
	}

	private Avion crearAvionHelicoptero() {
		Avion avionHelicoptero = FabricaAviones
				.makeAvionHelicoptero(torreDeControl);
		torreDeControl.agregarAvion(avionHelicoptero);
		vistaJuego.avionHelicopteroCreado(avionHelicoptero);
		return avionHelicoptero;
	}

	private Avion crearAvionPesado() {
		Avion avionPesado = FabricaAviones.makeAvionPesado(torreDeControl, nivel.getVelocidad());
		torreDeControl.agregarAvion(avionPesado);
		vistaJuego.avionPesadoCreado(avionPesado);
		return avionPesado;
	}

	public Mapa getMapa() {
		return this.nivel.getMapa();
	}

	public Nivel getNivel() {
		return nivel;
	}

	public ITorreDeControl getTorreDeControl() {
		return torreDeControl;
	}

	public Integer getCantidadAvionesAterrizados() {
		return cantidadAvionesAterrizados;
	}

}
